import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;

public class Mp3ToPcmConverter {

    /**
     * Converts an MP3 audio file to PCM format (stored in a WAV file).
     *
     * @param mp3InputFile  The path to the input MP3 file.
     * @param pcmOutputFile The path where the output WAV file (containing PCM data) will be saved.
     * @throws UnsupportedAudioFileException If the audio file format is not supported (e.g., invalid MP3 or missing SPI).
     * @throws IOException                   If an I/O error occurs during reading or writing.
     */
    public static void convert(String mp3InputFile, String pcmOutputFile)
            throws UnsupportedAudioFileException, IOException {

        File input = new File(mp3InputFile);
        File output = new File(pcmOutputFile);

        System.out.println("Starting conversion...");
        System.out.println("Input MP3: " + input.getAbsolutePath());
        System.out.println("Output WAV (PCM): " + output.getAbsolutePath());

        // Use try-with-resources to ensure streams are closed automatically
        try (AudioInputStream mp3Stream = AudioSystem.getAudioInputStream(input)) {

            // Get the format of the input MP3 stream
            AudioFormat sourceFormat = mp3Stream.getFormat();
            System.out.println("Source Format: " + sourceFormat);

            // Define the target PCM format
            // We want PCM_SIGNED, same sample rate, 16-bit depth, same channels,
            // calculated frame size, same frame rate, little-endian byte order.
            AudioFormat pcmFormat = new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED, // Encoding
                    sourceFormat.getSampleRate(),    // Sample Rate
                    16,                              // Sample Size (bits) - common for WAV
                    sourceFormat.getChannels(),      // Channels
                    sourceFormat.getChannels() * 2,  // Frame Size (Channels * Sample Size in bytes)
                    sourceFormat.getSampleRate(),    // Frame Rate
                    false                            // Little Endian (true for big endian)
            );
            System.out.println("Target PCM Format: " + pcmFormat);

            // Check if the conversion is supported
            if (!AudioSystem.isConversionSupported(pcmFormat, sourceFormat)) {
                System.err.println("Conversion not supported. Check if MP3SPI is in the classpath.");
                // Optionally, try a different PCM format (e.g., different bit depth)
                // Or throw a more specific exception
                throw new UnsupportedAudioFileException(
                        "Conversion from " + sourceFormat + " to " + pcmFormat + " not supported.");
            }

            // Get the converted stream (PCM)
            try (AudioInputStream pcmStream = AudioSystem.getAudioInputStream(pcmFormat, mp3Stream)) {

                // Write the PCM stream to the output WAV file
                int bytesWritten = AudioSystem.write(pcmStream, AudioFileFormat.Type.WAVE, output);

                System.out.println("Conversion successful!");
                System.out.println("Bytes written to WAV file: " + bytesWritten);
            }

        } catch (UnsupportedAudioFileException e) {
            System.err.println("Error: Audio file format not supported. Is the file a valid MP3?");
            System.err.println("Ensure the MP3SPI library and its dependencies (JLayer, Tritonus Share) are in the classpath.");
            throw e; // Re-throw the exception
        } catch (IOException e) {
            System.err.println("Error during file I/O.");
            throw e; // Re-throw the exception
        }
    }

    // --- Example Usage ---
    public static void main(String[] args) {
        // --- IMPORTANT ---
        // Replace with the actual paths to your files!
        String inputMp3 = "path/to/your/audio.mp3";
        String outputWav = "path/to/your/output.wav";
        // --- -------------

        File mp3 = new File(inputMp3);
        if (!mp3.exists()) {
            System.err.println("Error: Input MP3 file not found: " + inputMp3);
            System.err.println("Please update the 'inputMp3' variable in the main method.");
            return;
        }

        // Ensure the output directory exists (optional, but good practice)
        File outputDir = new File(outputWav).getParentFile();
        if (outputDir != null && !outputDir.exists()) {
            if (outputDir.mkdirs()) {
                System.out.println("Created output directory: " + outputDir.getAbsolutePath());
            } else {
                System.err.println("Failed to create output directory: " + outputDir.getAbsolutePath());
                // Might want to stop here depending on requirements
            }
        }


        try {
            convert(inputMp3, outputWav);
        } catch (UnsupportedAudioFileException e) {
            System.err.println("Conversion failed: Unsupported audio format.");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Conversion failed: I/O error.");
            e.printStackTrace();
        }
    }
}